/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.lang.Nullable;

/**
 * BeanDefinition描述了一个bean实例，它具有属性值，构造函数参数值以及具体实现提供的更多信息。
 *
 * 这只是一个最小的接口：主要目的是允许 {@link BeanFactoryPostProcessor}
 * （如{@link PropertyPlaceholderConfigurer} ）内省并修改属性值和其他bean元数据。
 *
 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    /**
     * 单例模式
     */
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    /**
     * 原型模式
     */
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


    /**
     * 通常对应于用户定义的bean
     */
    int ROLE_APPLICATION = 0;

    /**
     * Role hint indicating that a {@code BeanDefinition} is a supporting
     * part of some larger configuration, typically an outer
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition}.
     * {@code SUPPORT} beans are considered important enough to be aware
     * of when looking more closely at a particular
     * {@link org.springframework.beans.factory.parsing.ComponentDefinition},
     * but not when looking at the overall configuration of an application.
     */
    int ROLE_SUPPORT = 1;

    /**
     * 通常对应于完全属于{@link org.springframework.beans.factory.parsing.ComponentDefinition}的内部工作的bean
     */
    int ROLE_INFRASTRUCTURE = 2;


    // Modifiable attributes

    /**
     * 设置此BeanDefinition的父BeanDefinition的名称（如果有）。
     */
    void setParentName(@Nullable String parentName);

    /**
     * 返回此BeanDefinition的父BeanDefinition的名称（如果有）。
     */
    @Nullable
    String getParentName();

    /**
     * 指定此bean定义的bean类名称。
     * 可以在bean工厂后处理期间修改类名，*=通常用解析后的变体替换原始类名。
     * @see #setParentName
     * @see #setFactoryBeanName
     * @see #setFactoryMethodName
     */
    void setBeanClassName(@Nullable String beanClassName);

    /**
     * 返回此bean定义的当前bean类名.
     * 请注意，这不一定是运行时使用的实际类名，例如，子类定义覆盖/继承其父类的类名。
     * 此外，这可能只是调用工厂方法的类，或者在工厂bean引用调用方法的情况下甚至可能为空。
     * 因此，不要认为这是运行时的权威bean类型，而仅用于在单个bean定义级别进行解析。
     * @see #getParentName()
     * @see #getFactoryBeanName()
     * @see #getFactoryMethodName()
     */
    @Nullable
    String getBeanClassName();

    /**
     * 设置作用域
     */
    void setScope(@Nullable String scope);

    /**
     * 返回此bean的当前目标作用域的名称，
     */
    @Nullable
    String getScope();

    /**
     * 是否懒加载，仅适用于单例bean
     */
    void setLazyInit(boolean lazyInit);

    /**
     * 是否懒加载，仅适用于单例bean
     */
    boolean isLazyInit();

    /**
     * 设置此bean依赖于初始化的bean的名称。
     * bean工厂将保证首先初始化这些bean。
     */
    void setDependsOn(@Nullable String... dependsOn);

    /**
     * 返回此bean依赖的bean名称。
     */
    @Nullable
    String[] getDependsOn();

    /**
     * 设置此bean是否可以自动连接到其他bean。
     * 请注意，此标志旨在仅影响基于类型的自动装配。
     * 它不会影响名称的显式引用，如果指定的bean没有标记为autowire候选，
     * 它甚至会被解析。因此，如果名称匹配，名称自动装配将注入bean。
     */
    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * 返回此bean是否可以自动连接到其他bean中。
     */
    boolean isAutowireCandidate();

    /**
     * 设置此bean是否为主要autowire候选者
     * 如果这个值对于多个匹配的候选者中的一个bean来说是{@code true}，那么它将作为打破平局。
     */
    void setPrimary(boolean primary);

    /**
     * 此bean是否是主要的autowire候选者.
     */
    boolean isPrimary();

    /**
     * 设置FactoryBean
     */
    void setFactoryBeanName(@Nullable String factoryBeanName);

    /**
     * 返回FactoryBean的名字
     */
    @Nullable
    String getFactoryBeanName();

    /**
     * 指定FactoryMethod
     */
    void setFactoryMethodName(@Nullable String factoryMethodName);

    /**
     * 获取FactoryMethodName
     */
    @Nullable
    String getFactoryMethodName();

    /**
     * Return the constructor argument values for this bean.
     * <p>The returned instance can be modified during bean factory post-processing.
     * @return the ConstructorArgumentValues object (never {@code null})
     */
    ConstructorArgumentValues getConstructorArgumentValues();

    /**
     * 如果为此bean定义了构造函数参数值，则返回true。
     * @since 5.0.2
     */
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    /**
     * 返回要应用于bean的新实例的属性值.
     */
    MutablePropertyValues getPropertyValues();

    /**
     * 如果为此bean定义了属性值，则返回true。
     */
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }


    // Read-only attributes

    /**
     * 是否为单例模式
     */
    boolean isSingleton();

    /**
     * 是否为原型模式
     */
    boolean isPrototype();

    /**
     * 是否为Abstract
     */
    boolean isAbstract();

    /**
     * Get the role hint for this {@code BeanDefinition}. The role hint
     * provides the frameworks as well as tools with an indication of
     * the role and importance of a particular {@code BeanDefinition}.
     * @see #ROLE_APPLICATION
     * @see #ROLE_SUPPORT
     * @see #ROLE_INFRASTRUCTURE
     */
    int getRole();

    /**
     * 返回此bean定义的描述.
     */
    @Nullable
    String getDescription();

    /**
     * 返回此bean定义来的Resource的描述（为了在出现错误时显示上下文）。
     */
    @Nullable
    String getResourceDescription();

    /**
     * 返回原始BeanDefinition，如果没有，则返回{@code null}。
     * <p>遍历originator链以查找用户定义的原始BeanDefinition。
     */
    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}
